#include "SM4Encrypt.h"
SM4Encrypt* SM4Encrypt::m_pInstance = NULL;
QMutex SM4Encrypt::m_Mutex;

//SM4Encrypt::SM4Encrypt()
//{

//}
SM4Encrypt::SM4Encrypt(QObject *parent) :
    QObject(parent)
{

}
void SM4Encrypt::Init(){

    qDebug()<<"SM4Encrypt Init Start\n";
    m_SignedDataRaw="<html>The plaintext message.</html>";
    isInit=false;
    timer = new QTimer(this);
    timer->setInterval(10000);
    timer->setSingleShot(true);
    connect(timer, SIGNAL(timeout()), this, SLOT(timeoutSlot()));
    timer->start();
}

void SM4Encrypt::ImportSessionKey(QByteArray key)
{

    nRet = SE_ImportSessionKey(hEnv, SGD_SM4_ECB, (unsigned char *)key.data(), key.count());
    if(SAR_OK !=nRet)
    {
        qDebug()<<"SE_ImportSessionKey fail. ret :  \n"<< nRet;
        return;
    }
    isInit=true;
    qDebug()<<"SE_ImportSessionKey success";
}

QByteArray SM4Encrypt::EncryptBySM4(QByteArray data)
{
    unsigned char ucCipher[2048];
    unsigned int ucCipherLen=sizeof(ucCipher);

   // QByteArray base64data=data.toBase64();
    QByteArray ucQbytearray;
    unsigned char *nData= (unsigned char *) data.data();
    unsigned int nDataLen=data.length();//strlen((char*)nData);
    nRet = SE_SymmOp(hEnv, 0, NULL, 0,nData, nDataLen, ucCipher, &ucCipherLen);
    if(SAR_OK != nRet)
    {
        qDebug()<<"SE_SymmOp (encrypt) fail ret : \n"<<nRet;
        return ucQbytearray; //goto fail;
    }
    ucQbytearray=QByteArray::fromRawData((char*)ucCipher,ucCipherLen);
    qDebug()<<"SE_SymmOp (encrypt) success.nDataLen:%d；nCipherLen:%d\n"<<ucQbytearray.toBase64()<<ucCipherLen;

   // DecryptBySM4(ucQbytearray);
    return ucQbytearray.toBase64();
}

QByteArray SM4Encrypt::DecryptBySM4(QByteArray data)
{
    unsigned char ucCipher[2048];
    unsigned int ucCipherLen=sizeof(ucCipher);
    QByteArray ucQbytearray;
//    QByteArray base64data=data.toBase64();
    qDebug()<<"DecryptBySM4 Base64 "<<data;
    QByteArray data_unbase64=QByteArray::fromBase64(data);
    unsigned char *nData= (unsigned char *) data_unbase64.data();
    unsigned int nDataLen=data_unbase64.length();
    qDebug()<<"nDataLen"<<nDataLen;
    nRet = SE_SymmOp(hEnv, 1, NULL, 0,nData, nDataLen, ucCipher, &ucCipherLen);
    if(SAR_OK != nRet)
    {
        qDebug()<<"SE_SymmOp (DecryptBySM4 ) fail ret : \n"<<nRet;
        return ucQbytearray; //goto fail;
    }
    ucQbytearray=QByteArray::fromRawData((char*)ucCipher,ucCipherLen);
    qDebug()<<"SE_SymmOp (DecryptBySM4 ) success.nDataLen:%d；nCipherLen:%d\n"<<ucQbytearray.toBase64()<<ucCipherLen;



  /*  QString str;
    for(int i=0;i<ucQbytearray.size();i++)
    {
        str+=QString("%1").arg((unsigned char)ucQbytearray.at(i),2,16,QLatin1Char('0'))+' ';
    }
    qDebug()<<"DecryptBySM4 data::"<<str;  //打印十六进制数据
    */
    print16FormatData(ucQbytearray);
    return ucQbytearray;
}

void SM4Encrypt::print16FormatData(QByteArray data)
{
    qDebug()<<"SM4Encrypt:: print16FormatData\n";
    QString str;
    for(int i=0;i<data.size();i++)
    {
        str+=QString("%1").arg((unsigned char)data.at(i),2,16,QLatin1Char('0'))+' ';
    }
    qDebug()<<"print data::"<<str;  //打印十六进制数据
}

qint32 SM4Encrypt::initWXTPlatformDevice()
{

    qDebug()<<"SM4Encrypt initWXTPlatformDevice \n";
    char* szDeviceId;
    System *system = System::getInstance();

    QString uuid = system->ReadUuid();
    uuid  ="356516100008031";

    QByteArray ba = uuid.toLatin1();
    szDeviceId = ba.data();

    nRet = SE_Initialize(&hEnv,0,szDeviceId,NULL,NULL,NULL);
    if(SAR_OK != nRet){
        qDebug()<<"SE_Initialize fail ret "<<nRet;
    }
    else
    {
            //get se id
        memset(&m_stSeAppInfo,0,sizeof(SEAPPINFO));
        nRet = SE_GetSEInfo(hEnv,&m_stSeAppInfo);
        if(SAR_OK != nRet)
        {
            qDebug()<<"SE_GetSEInfo fail ret "<<nRet;
           // printf("SE_Initialize fail ret : 0x%08X \n", nRet);
            return 1;// goto fail;
        }
        for(int i=0; i<16; i++)
        {
            sprintf(m_szSeId+2*i, "%02x", m_stSeAppInfo.SEID[i]);
        }
        qDebug()<<"SE_GetSEID success. SEID :"<<m_szSeId;

        //export certificate
      //  unsigned int SignedCertData_len=sizeof(m_SignedCertData);
        m_SignedCertData_len=8192;
        nRet = SE_ExportCertificate(hEnv, 1, m_SignedCertData, &m_SignedCertData_len);
        qDebug()<<"SE_ExportCertificate m_SignedCertData_len  "<<m_SignedCertData_len;
        if(SAR_OK != nRet)
        {
            qDebug()<<"SE_ExportCertificate fail ret :"<<nRet;
            return nRet;// goto fail;
        }

        char byte1[8192];
        memcpy(byte1,m_SignedCertData,m_SignedCertData_len);
        qDebug()<<"SE_ExportCertificate success. p10 : %s \n"<< QString::fromUtf8(byte1);


       // isInit=true;
        timer->stop();
        emit sm4InitComlete();

        return SAR_OK;

    }
    return 1;
}

QByteArray SM4Encrypt::getGenP7AuthData()
{
   // char szData[] = "<html>The plaintext message.</html>";
    unsigned char ucSignedData[8192] = {0};
    unsigned int nSignedDataLen = sizeof(ucSignedData);
  //  QByteArray SignedDataRawBase64=getGenP7AuthDataRaw();
    unsigned char *nData= (unsigned char *) m_SignedDataRaw.data();
    unsigned int nDataLen=m_SignedDataRaw.length();
    nRet = SE_GenP7AuthData(hEnv, nData,nDataLen, ucSignedData, &nSignedDataLen);
    if(SAR_OK != nRet)
    {
        qDebug()<<"SE_GenP7AuthData fail. ret : 0x%08X \n"<<nRet;
        return 0;// goto fail;
    }
    QByteArray res=QByteArray::fromRawData((char*)ucSignedData,nSignedDataLen);
    return res;
}

QByteArray SM4Encrypt::getGenP7AuthDataRaw()
{
    return m_SignedDataRaw.toBase64();
}

bool SM4Encrypt::getIsInit()
{
    return isInit;
}

char *SM4Encrypt::getSeId()
{
    return m_szSeId;
}

QByteArray SM4Encrypt::getSignedCert()
{
//    char byte1[8192];
//    memcpy(byte1,m_SignedCertData,m_SignedCertData_len);
//    QString data=QString::fromUtf8(byte1);
//    qDebug()<<"getSignedCert\n"<<data ;


    char  temp[8192];
   // qDebug()<<"getSignedCert1"<<m_SignedCertData;
    memcpy(temp,m_SignedCertData,8192);
  //  qDebug()<<"getSignedCert2";
    QByteArray q(temp);
 //   qDebug()<<"getSignedCert3";
    return q;
}

void SM4Encrypt::timeoutSlot()
{
    qDebug()<<"timeoutSlot SM4Encrypt timeoutSlot  ";
    initWXTPlatformDevice();


}
